/**
 * Created by clakeboy on 16/9/13.
 */
import conf from '../config'
import {
    Calculate,
    GetElementXY,
    CloneObject,
    String2Hex,
    Extend,
    Storage
} from '../util/common';

//定义常量
const SELECT_ALPHA = .3; //选择框背景色透明度
const SELECT_COLOR = 0xB0E2FF; //选择框背景色
const SELECT_LINE_COLOR = 0x666666; //选择框边框颜色

export default class Area {
    constructor(cfg,parent) {
        //全局配置
        this.initCFG = Extend(conf,cfg);
        this.cfg = CloneObject(this.initCFG);
        //有数据的区块数
        this.gridCount = 0;
        //鼠标是否被按下
        this.mouseDown = false;
        //父滚动节点
        this.parentEml = parent || document.body;
        //主画布
        this.eml = document.getElementById(this.cfg.element);
        this.eml.oncontextmenu = ()=>{return false;};
        this.eml.point = GetElementXY(this.eml,this.parentEml);
        //初始化方法集
        this._initPIXI();
        this._initGridData();
        this._initEvents();
        this._initGridArea();
        this._initstaffMouseSelect();
        this._initStaffEmpty();
        this._initStaff();
        this._initMouseEvent();
        this._initScale();
        this._initRowCol();
        this._initFPS();
        this._initHistory();
        this._initBlockTip();
        this._initGlobalKeyEvent();
    }

    /**
     * 初始化PIXI工具
     * @private
     */
    _initPIXI() {
        this.width = this.cfg.cols * this.cfg.rectWidth + this.cfg.lineLength;
        this.height = this.cfg.rows * this.cfg.rectHeight + this.cfg.lineLength;
        this.eml.style.width = this.width + 'px';
        this.eml.style.height = this.height + 'px';
        this.renderer = new PIXI.autoDetectRenderer(this.width,this.height,{
            transparent:true,
            resolution: window.devicePixelRatio || 1,
            preserveDrawingBuffer:true
        });
        this.eml.appendChild(this.renderer.view);
        this.stage = new PIXI.Container();
    }

    /**
     * 初始化FPS显示文字
     * 配置文件内配置是否显示 fps:true
     * @private
     */
    _initFPS() {
        if (this.cfg.fps) {
            this.fps = new PIXI.Text('FPS: 0',{fontFamily:'Arial',fontSize:10,fill:0xff0000});
            this.stage.addChild(this.fps);
        } else {
            this.stage.removeChild(this.fps);
        }
    }

    /**
     * 初始化全局键盘
     * @private
     */
    _initGlobalKeyEvent() {
        window.addEventListener('keydown',(e)=>{
            if (e.ctrlKey && e.altKey && e.keyCode==80) {
                var image = this.cutPicture();
                var w=window.open('about:blank','image from canvas');
                w.document.write("<img src='"+image+"' alt='from canvas'/>");
            }
        },false);
    }

    /**
     * 初始化区块提示框
     * @private
     */
    _initBlockTip() {
        this.blockTip = {
            gs:new PIXI.Graphics(),
            txt:new PIXI.Text('',{fontFamily:'',fontSize:10,fill:0x666666,lineHeight:20})
        };
        this.blockTip.gs.addChild(this.blockTip.txt);
        this.stage.addChild(this.blockTip.gs);
    }

    /**
     * 显示区块提示框
     * @private
     */
    _showBlockTip() {
        if (!this.currentBlock) return;
        var gs = this.blockTip.gs,
            txt = this.blockTip.txt,
            template, w, h, x, y, offset=20;
        gs.clear();
        txt.text = '';
        var data = this.gridData[this.currentBlock.row-1][this.currentBlock.col-1];
        if (data) {
            template = this.cfg.blockTip.template;
            for (var k in data) {
                template = template.replace("{"+k+"}",k=='color'?PIXI.utils.hex2string(data[k]).toUpperCase():data[k]);
            }
            template = template.replace(/{.+}/g,'无');
            txt.text = template;
            w = txt.width + 10;
            h = txt.height + 5;
            x = this.currentBlock.x + offset;
            y = this.currentBlock.y + offset;
            x = x + w > this.width ? x - w - (offset + 5)  : x;
            y = y + h > this.height ? y - h - (offset+5) : y;

            gs.lineStyle(1,0x999999);
            gs.beginFill(0xFDF5E6);
            gs.drawRect(x,y,w,h);
            gs.endFill();

            txt.x = x + (w/2 - txt.width/2);
            txt.y = y + (h/2 - txt.height/2) + 3;
        }
    }

    /**
     * 初始化显示
     * @private
     */
    _initRowCol() {
        var gs = new PIXI.Graphics(),
            txt = new PIXI.Text('',{fontFamily:'Arial',fontSize:10,fill:0x666666});
        gs.addChild(txt);
        gs.interactive = true;
        gs.on('mousedown',function(e){
            console.log(e);
        });
        this.stage.addChild(gs);
        this.showRowCol = {
            gs:gs,
            txt:txt
        };
        this.renderer.view.addEventListener('mousemove',(e)=>{
            var x = e.offsetX - this.cfg.lineLength,
                y = e.offsetY - this.cfg.lineLength,
                row,col,sel,grid,point;
            row = Calculate(y,this.cfg.rectHeight);
            col = Calculate(x,this.cfg.rectWidth);
            sel = this.selectArea ? this.selectArea.num : '0';
            grid = this.gridCount;
            point = this.staff.ver[row-1] + ',' + this.staff.hor[col-1];

            this.showRowCol.txt.text = this.cfg.bottomTip
                .replace('{grid}',grid)
                .replace('{selected}',sel)
                .replace('{pointer}',point);
            this.currentBlock = {
                row:row <= 0 ? 1 : row,
                col:col <= 0 ? 1 : col,
                x:e.offsetX,
                y:e.offsetY
            };
        },false);
    }

    /**
     * 显示当前鼠标所在行列
     * @private
     */
    _showRowCol() {
        var x = this.cfg.lineLength, y, w,h,offsetBottom,offsetLeft,offset=0,
            gs = this.showRowCol.gs,
            txt = this.showRowCol.txt;
        var scroll = this.parentEml;

        offsetBottom = scroll.scrollTop + scroll.clientHeight - this.eml.point.top;
        offsetLeft = scroll.scrollLeft - this.eml.point.left;
        if (scroll == document.body && scroll.scrollWidth > scroll.clientWidth) {
            offset = 20;
        }

        w = txt.width + 10;
        h = txt.height + 10;

        if (offsetBottom > this.height) {
            y = this.height - h;
        } else {
            y = offsetBottom - h;
        }

        if (offsetLeft <= 0) {
            x = this.cfg.lineLength;
        } else {
            x = offsetLeft;
        }

        y -= offset;

        gs.clear();
        gs.lineStyle(1,0xF0E68C,.3);
        gs.beginFill(0xEE9A49,.2);
        gs.drawRect(x,y,w,h);
        gs.endFill();
        txt.x = x + (w/2 - txt.width/2);
        txt.y = h/2 - txt.height/2 + y;
    }

    /**
     * 初始化网格数据
     * @private
     */
    _initGridData() {
        var data = new Array(this.cfg.rows);
        for (var i=0;i<data.length;i++) {
            data[i] = new Array(this.cfg.cols);
        }
        this.gridData = data;
        if (!this.datags) {
            this.datags = new PIXI.Graphics();
            this.stage.addChild(this.datags);
        }
    }

    /**
     * 初始化历史记录
     * @private
     */
    _initHistory() {
        this.historyIdx = 0;
        // this.historys = new Array(20);
        this._addHistory(CloneObject(this.gridData));
    }

    _addHistory(data) {
        this.historyIdx += 1;
        if (this.historyIdx >= 20) {
            this.historyIdx = 0;
        }
        Storage.set('history_'+this.historyIdx,data);
    }

    /**
     * 开始画所有数据区块
     * @private
     */
    _drawData() {
        this.datags.clear();
        this.datags.removeChildren();
        var num = 0;
        for (var i=0;i<this.gridData.length;i++) {
            for (var k=0;k<this.gridData[i].length;k++) {
                if (this.gridData[i][k]) {
                    this._drawGridColumn(this.gridData[i][k]);
                    num++;
                }
            }
        }
        this.gridCount = num;
    }

    /**
     * 画单个区块
     * @param data 区块数据
     * @private
     */
    _drawGridColumn(data) {
        var x,y;
        x = (data.col - 1) * this.cfg.rectWidth + this.cfg.lineLength;
        y = (data.row - 1) * this.cfg.rectHeight + this.cfg.lineLength;
        this.datags.beginFill(data.color);
        this.datags.drawRect(x,y,this.cfg.rectWidth,this.cfg.rectHeight);
        this.datags.endFill();

        var text,color;
        if (typeof data.text == 'object') {
            text = data.text.text;
            color = String2Hex(data.text.color);
        } else {
            text = data.text || data.block;
            //color = 0xFFFFFF - data.color; //- 0x333333;
            color = 0x333333;
        }
        var txt = new PIXI.Text(text,{fontFamily:'Arial',fontSize:9,fill:color});
        txt.x = x + (this.cfg.rectWidth/2-txt.width/2);
        txt.y = y + (this.cfg.rectHeight/2-txt.height/2);
        this.datags.addChild(txt);
    }

    /**
     * 初始化事件系统
     */
    _initEvents() {
        this.eventNames = {
            //选中区块事件
            select:null, // (columns)=>{}
            blockTip:null //(text)=>{return text||false}
        };
    }

    /**
     * 初始化区域线框
     */
    _initGridArea() {
        var gs,i,startX = this.cfg.lineLength,startY = this.cfg.lineLength;
        if (this.gridgs) {
            gs = this.gridgs;
        } else {
            gs = new PIXI.Graphics();
            this.stage.addChild(gs);
            this.gridgs = gs;
        }

        //画网格线
        gs.lineStyle(1,0xdedede);
        gs.moveTo(startX,startY);

        //画行
        for (i = 1;i <= this.cfg.rows;i++) {
            gs.moveTo(startX,startY + i * this.cfg.rectHeight);
            gs.lineTo(this.width,startY + i * this.cfg.rectHeight);
        }
        //画列
        for (i = 1;i <= this.cfg.cols;i++) {
            gs.moveTo(startX + i * this.cfg.rectWidth,startY);
            gs.lineTo(startX + i * this.cfg.rectWidth,this.height);
        }
    }

    /**
     * 初始化标尺留空值
     * @private
     */
    _initStaffEmpty() {
        this.cfg.staffEmpty.forEach((item)=>{
            this.staffEmpty[item.type][item.value] = true;
        });
    }

    /**
     * 初始化标尺线
     *
     * @private
     */
    _initStaff() {
        var startX = this.cfg.lineLength,
            startY = this.cfg.lineLength,
            i,gs,txt,text,order;
        this.staff = {
            hor:[],
            ver:[]
        };
        if (this.staffgs) {
            gs = this.staffgs;
            gs.clear();
            gs.removeChildren();
        } else {
            gs = new PIXI.Graphics();
            this.stage.addChild(gs);
            this.staffgs = gs;
        }
        var txt_style = {
            fontFamily : 'Arial',fontSize:10,fill:0x666666
        };
        //画标尺线
        gs.lineStyle(1,0x000000);
        gs.moveTo(startX,0);
        gs.lineTo(startX,this.height);
        gs.moveTo(0,startY);
        gs.lineTo(this.width,startY);

        //画行 纵向坐标线文字
        var abc_start = 65+this.cfg.rows- 1,offset=0;
        for (i = 1;i <= this.cfg.rows;i++) {
            text = '';
            if (this.staffEmpty['ver'][i-1]) {
                offset-=1;
            } else {
                order = typeof this.cfg.staff.order == 'string' ? this.cfg.staff.order : this.cfg.staff.order.ver;
                if (order == 'asc') {
                    text = ''+(i+offset);
                    if (this.cfg.staff.type == 'abc') {
                        text = String.fromCharCode((i+offset)-1+65);
                    }
                } else {
                    text = this.cfg.rows - offset - (i-1);
                    if (this.cfg.staff.type == 'abc') {
                        text = String.fromCharCode(abc_start - offset - (i-1));
                    }
                }
            }
            //标尺线文字
            txt = new PIXI.Text(text,txt_style);
            txt.x = this.cfg.staff.type == 'abc' ? this.cfg.lineLength/2 - txt.width/2 : this.cfg.lineLength - (txt.width + 2);
            txt.y = this.cfg.lineLength + (i-1) * this.cfg.rectHeight +
                (this.cfg.rectHeight / 2 - txt.height / 2);
            gs.addChild(txt);
            this.staff.ver.push(text);
        }
        //画列 横向坐标线文字
        offset=0;
        for (i = 1;i <= this.cfg.cols;i++) {
            text = '';
            if (this.staffEmpty['hor'][i-1]) {
                offset-=1;
            } else {
                order = typeof this.cfg.staff.order == 'string' ? this.cfg.staff.order : this.cfg.staff.order.hor;
                if (order == 'asc') {
                    text = ''+(i+offset);
                } else {
                    text = this.cfg.cols - offset - (i-1);
                }
            }

            //标尺线文字
            txt = new PIXI.Text(text,txt_style);
            txt.x = this.cfg.lineLength + (i-1) * this.cfg.rectWidth +
                (this.cfg.rectWidth / 2 - txt.width / 2);
            txt.y = this.cfg.lineLength/2 - txt.height/2;
            gs.addChild(txt);
            this.staff.hor.push(text);
        }
    }

    /**
     * 初始化标尺选中功能
     * @private
     */
    _initstaffMouseSelect() {
        this.staffMousegs = new PIXI.Graphics();
        this.staffMouseSelectgs = new PIXI.Graphics();
        this.stage.addChild(this.staffMouseSelectgs);
        this.stage.addChild(this.staffMousegs);
        this.staffEmpty = {
            hor:new Array(this.cfg.cols),
            ver:new Array(this.cfg.rows)
        };
        this.renderer.view.addEventListener('mousemove',(e)=>{
            var x = e.offsetX,y= e.offsetY,ll = this.cfg.lineLength,sx,sy;
            if (x > ll && y < ll) { //横向标尺内
                this.staffMousegs.clear();
                var hor = Calculate(x-ll,this.cfg.rectWidth);
                sx = (hor - 1) * this.cfg.rectWidth + ll;
                sy = 0;
                this.staffMousegs.beginFill(0xFF7F24,.5);
                this.staffMousegs.drawRect(sx,sy,this.cfg.rectWidth,ll);
                this.staffMousegs.endFill();
                this.staffMouseSelect = {
                    type:'hor',
                    value:hor
                };
            } else if (y > ll && x < ll) { //纵向标尺内
                this.staffMousegs.clear();
                var ver = Calculate(y-ll,this.cfg.rectHeight);
                sx = 0;
                sy = (ver - 1) * this.cfg.rectHeight + ll;
                this.staffMousegs.beginFill(0xFF7F24,.5);
                this.staffMousegs.drawRect(sx,sy,ll,this.cfg.rectHeight);
                this.staffMousegs.endFill();
                this.staffMouseSelect = {
                    type:'ver',
                    value:ver
                };
            } else {
                this.staffMousegs.clear();
                this.staffMouseSelect = null;
            }
        },false);

        this.renderer.view.addEventListener('mouseup',()=>{
            if (this.staffMouseSelect) {
                this.staffSelect = CloneObject(this.staffMouseSelect);
                this.staffMouseSelectgs.clear();
                var x, y, w, h;
                switch (this.staffSelect.type) {
                    case 'hor':
                        x = (this.staffSelect.value - 1) * this.cfg.rectWidth + this.cfg.lineLength;
                        y = 0;
                        w = this.cfg.rectWidth;
                        h = this.cfg.lineLength;
                        break;
                    case 'ver':
                        x = 0;
                        y = (this.staffSelect.value - 1) * this.cfg.rectHeight + this.cfg.lineLength;
                        w = this.cfg.lineLength;
                        h = this.cfg.rectWidth;
                        break;
                }
                this.staffMouseSelectgs.beginFill(0x53868B,.3);
                this.staffMouseSelectgs.drawRect(x,y,w,h);
                this.staffMouseSelectgs.endFill();
            }
        },false);
    }

    /***
     * 初始化鼠标事件
     */
    _initMouseEvent() {
        //选中域画板
        this.selectgs = new PIXI.Graphics();
        //鼠标拖动区域画板
        this.mousegs = new PIXI.Graphics();
        this.stage.addChild(this.mousegs);
        this.stage.addChild(this.selectgs);
        this.renderer.view.addEventListener('mousemove',(e)=>{
            if (this.mouseDown) {
                this._mouseEvent(e);
            }
        },false);
        this.renderer.view.addEventListener('mousedown',(e)=>{
            if (e.button === 2) {
                return;
            }
            this.mouseDown = true;
            this.mouse = {
                x:e.offsetX,
                y:e.offsetY
            };
        },false);
        this.renderer.view.addEventListener('mouseup',(e)=>{
            if (e.button === 2) {
                this._clearSelectArea();
            } else {
                this.mouseDown = false;
                this.mousegs.clear();
                this.mouseEnd = {
                    x:e.offsetX,
                    y:e.offsetY
                };
                this._calculateSelect();
            }
        },false);
    }

    /**
     * 鼠标事件处理
     */
    _mouseEvent(e) {
        this.mousegs.clear();
        this.mousegs.lineStyle(1,SELECT_LINE_COLOR);
        this.mousegs.beginFill(SELECT_COLOR,SELECT_ALPHA);
        this.mousegs.moveTo(this.mouse.x,this.mouse.y);
        this.mousegs.lineTo(this.mouse.x - (this.mouse.x - e.offsetX),this.mouse.y);
        this.mousegs.lineTo(e.offsetX,e.offsetY);
        this.mousegs.lineTo(this.mouse.x, this.mouse.y - (this.mouse.y - e.offsetY));
        this.mousegs.lineTo(this.mouse.x, this.mouse.y);
    }

    _initScale() {
        this.scale = 1;
        //this.eml.addEventListener('mousewheel',(e)=>{
        //    var scroll = e.wheelDelta / 120 * .1;
        //    this.scale += scroll;
        //    this.renderer.view.style.transform = 'scale('+this.scale+','+this.scale+')';
        //    console.log(parseInt(this.scale * 100) + '%');
        //},false);
    }

    /**
     * 计算选中的区域并加入画中区域
     */
    _calculateSelect() {
        var start={},end={},
            leftPoint,rightPoint;
        if (this.mouse.x > this.mouseEnd.x) {
            if (this.mouse.y > this.mouseEnd.y) {
                leftPoint = this.mouseEnd;
                rightPoint = this.mouse;
            } else {
                leftPoint = {
                    x:this.mouseEnd.x,
                    y:this.mouse.y
                };
                rightPoint = {
                    x:this.mouse.x,
                    y:this.mouseEnd.y
                };
            }
        } else {
            if (this.mouseEnd.y > this.mouse.y) {
                leftPoint = this.mouse;
                rightPoint = this.mouseEnd;
            } else {
                leftPoint = {
                    x:this.mouse.x,
                    y:this.mouseEnd.y
                };

                rightPoint = {
                    x:this.mouseEnd.x,
                    y:this.mouse.y
                };
            }
        }

        //所有坐标去除标尺长度
        leftPoint.x -= this.cfg.lineLength;
        leftPoint.y -= this.cfg.lineLength;
        rightPoint.x -= this.cfg.lineLength;
        rightPoint.y -= this.cfg.lineLength;

        start.row = Calculate(leftPoint.y,this.cfg.rectHeight);
        start.col = Calculate(leftPoint.x,this.cfg.rectWidth);

        end.row = Calculate(rightPoint.y,this.cfg.rectHeight);
        end.col = Calculate(rightPoint.x,this.cfg.rectWidth);

        this.selectArea = {
            start:start, //起始行列
            end:end, //结束行列
            rows:(end.row-start.row+1), //选中多少行
            cols:(end.col-start.col+1), //选中多少列
            num:(end.col-start.col+1) * (end.row-start.row+1) //选中多少格
        };

        if (leftPoint.x < 0 ||
            leftPoint.y < 0 ||
            rightPoint.x < 0 ||
            rightPoint.y < 0) {
            return;
        }

        this._drawSelectArea(start,end);
    }

    /**
     * 画出选中的区域框
     * @param startRow
     * @param startCol
     * @param endRow
     * @param endCol
     * @constructor
     */
    _drawSelectArea(start,end) {
        this.selectgs.clear();
        this.selectgs.lineStyle(1,SELECT_LINE_COLOR);
        this.selectgs.beginFill(SELECT_COLOR,SELECT_ALPHA);
        this.selectgs.drawRect(
            (start.col-1)*this.cfg.rectWidth + this.cfg.lineLength,
            (start.row-1)*this.cfg.rectHeight + this.cfg.lineLength,
            (end.col-start.col+1)*this.cfg.rectWidth,
            (end.row-start.row+1)*this.cfg.rectHeight
        );
        this.selectgs.endFill();
    }

    /**
     * 清除选区
     * @private
     */
    _clearSelectArea() {
        this.selectgs.clear();
        this.staffMouseSelectgs.clear();
        this.selectArea = null;
    }

    /**
     * 生成内容
     */
    _render() {
        if (this.cfg.fps) {
            this.fps.text = 'FPS: ' +  this.ticker.FPS.toFixed(2);
        }
        this._showRowCol();
        this._showBlockTip();
        this.renderer.render(this.stage);
    }

    /**
     * 计算有数据的区块数量
     * @private
     */
    _countData() {
        var num = 0;
        this.gridData.forEach((row)=>{
            row.forEach((col)=>{
                if (col) {
                    num ++;
                } 
            });
        });
        
        this.gridCount = num;
    }

    /**
     * 显示或关闭FPS
     * @param flag bool
     */
    showFPS(flag) {
        this.cfg.fps = flag;
        this._initFPS();
    }

    /**
     * 加入事件监听方法
     * @param eventName
     * @param fn
     */
    on(eventName, fn) {
        if (this.eventNames[eventName]) {
            this.eventNames[eventName] = fn;
        }
    }

    /**
     * 重置区域大小
     * @param row 行
     * @param col 列
     */
    resizeGrid(row,col) {
        this.cfg.rows = parseInt(row);
        this.cfg.cols = parseInt(col);
        this.width = this.cfg.cols * this.cfg.rectWidth + this.cfg.lineLength;
        this.height = this.cfg.rows * this.cfg.rectHeight + this.cfg.lineLength;
        this.eml.style.width = this.width + 'px';
        this.eml.style.height = this.height + 'px';
        this.renderer.resize(this.width,this.height);
        this._initGridArea();
        this._initStaff();
        this._initGridData();
    }

    /**
     * 设置区域数据
     * @param color
     * @param type 排序类型 def|asc|desc
     * @param text
     * @param extra
     */
    setSelectArea(color, type=null, text=null, extra=null) {
        if (!this.selectArea) {
            return;
        }


        var data = Extend({},extra);
        if (color) {
            data['color'] = String2Hex(color);
        }

        if (text) {
            data['text'] = text;
        }

        // this.setData({
        //     color:color,
        //     text:text,
        //     extra:extra
        // },type,this.selectArea.start,this.selectArea.end);

        if (type) {
            this.setDataOrder(Extend(data,extra),type,this.selectArea.start,this.selectArea.end)
        } else {
            this.setData(Extend(data,extra),this.selectArea.start,this.selectArea.end);
        }

        this._drawData();
        this._clearSelectArea();
        this._addHistory(CloneObject(this.gridData));
    }

    /**
     * 设置所有数据到区块
     * @param data array
     */
    setAllArea(data) {
        data.forEach((item)=>{
            item.color = String2Hex(item.color);
            this.gridData[item.row-1][item.col-1] = item;
        });
        this._drawData();
        this._clearSelectArea();
        this._addHistory(CloneObject(this.gridData));
    }

    /**
     * 清除区域数据
     */
    removeSelectArea() {
        if (!this.selectArea) {
            return;
        }
        this.removeData(this.selectArea.start,this.selectArea.end);
        this._drawData();
        this._clearSelectArea();
        this._addHistory(CloneObject(this.gridData));
    }

    /**
     * 设置数据到网格
     * @param data 数据
     * @param order 排序类型 def|asc|desc
     *          {
     *            type:'def|asc|desc',
     *            step:'single|double'
     *            start:1
     *          }
     * @param start 开始区块坐标
     * @param end 结束区块坐标
     */
     setDataOrder(data,order,start,end=null) {
        var old_data,new_txt,ord,step;
        if (end) {
            step = order.step === 'double' ? 2 : 1;
            var sum_cols = end.col-start.col;
            if (order.type === 'desc') {
                this.staffEmpty['hor'].forEach((item,index)=>{
                    if (item && index < end.col) {
                        sum_cols-=1;
                    }
                });
            }
            for (var i=start.row;i<=end.row;i++) {
                if (this.staffEmpty['ver'][i-1]) {
                    continue;
                }
                if (order.type === 'def') {
                    ord = null;
                } else {
                    if (order.type==='desc') {
                        ord = order.start + sum_cols*step;
                    } else {
                        ord = order.start;
                    }
                }
    
                for (var k=start.col;k<=end.col;k++) {
                    if (this.staffEmpty['hor'][k-1]) {
                        continue;
                    }
                    old_data = this.gridData[i-1][k-1];
                    new_txt = this.staff.ver[i-1] + ':' + (ord || this.staff.hor[k-1]);
                    var new_data;
                    if (old_data) {
                        old_data['block'] = new_txt;
                        new_data = old_data;
                    } else {
                        new_data = {
                            row:i,
                            col:k,
                            block:new_txt,
                            color:0xEFEFEF
                        };
                    }
    
                    this.gridData[i-1][k-1] = Extend(new_data,data);
                    if (ord !== null) {
                        ord = order.type === 'asc' ? ord+step:ord-step;
                    }
                }
            }
        } else {
            if (!this.staffEmpty['ver'][start.row-1] && !this.staffEmpty['hor'][start.col-1]) {
                old_txt = this.staff.ver[start.row-1] + ':' + this.staff.hor[start.col-1];
                this.gridData[start.row-1][start.col-1]= Extend({
                    row:start.row,
                    col:start.col,
                    text:data.text?data.text:old_txt,
                    block:old_txt,
                    color:data.color
                },data.extra);
            }
        }
    }

    /**
     * 设置数据到网格非排序
     * @param data 数据
     * @param start 开始区块坐标
     * @param end 结束区块坐标
     */
    setData(data,start,end=null) {
        var old_data,old_txt;
        if (end) {
            for (var i=start.row;i<=end.row;i++) {
                if (this.staffEmpty['ver'][i-1]) {
                    continue;
                }
                for (var k=start.col;k<=end.col;k++) {
                    if (this.staffEmpty['hor'][k-1]) {
                        continue;
                    }
                    old_data = this.gridData[i-1][k-1];
                    old_txt = this.staff.ver[i-1] + ':' + this.staff.hor[k-1];
                    this.gridData[i-1][k-1] = Extend(old_data||{
                            row:i,
                            col:k,
                            block:old_txt
                        },data);
                }
            }
        } else {
            if (!this.staffEmpty['ver'][start.row-1] && !this.staffEmpty['hor'][start.col-1]) {
                old_txt = this.staff.ver[start.row-1] + ':' + this.staff.hor[start.col-1];
                this.gridData[start.row-1][start.col-1]= Extend({
                    row:start.row,
                    col:start.col,
                    text:data.text?data.text:old_txt,
                    block:old_txt,
                    color:data.color
                },data.extra);
            }
        }
    }

    /**
     * 从网格上删除数据
     * @param start
     * @param end
     */
    removeData(start,end=null) {
        if (end) {
            for (var i=start.row;i<=end.row;i++) {
                for (var k=start.col;k<=end.col;k++) {
                    this.gridData[i-1][k-1] = undefined;
                }
            }
        } else {
            this.gridData[start.row-1][start.col-1] = undefined;
        }
    }

    /**
     * 得到选中数据
     * @param isAll
     * @param isExits
     * @returns {*}
     */
    getData(isAll,isExits=true) {
        var is_select = this.selectArea ? true : false;
        if (!isAll && !is_select) {
            return [];
        }
        var start,rows,cols,i, k, data;
        if (isAll) {
            start = {
                row:1,
                col:1
            };
            rows = this.cfg.rows;
            cols = this.cfg.cols;
        } else {
            start=this.selectArea.start;
            rows=this.selectArea.rows;
            cols=this.selectArea.cols;
        }
        if (isExits) {
            data = [];
        } else {
            data = new Array(rows);
            for (i=0;i<rows;i++) {
                data[i] = new Array(cols);
            }
        }
        for (i=0;i<rows;i++) {
            for (k=0;k<cols;k++) {
                if (!this.gridData[i+start.row-1][k+start.col-1]) continue;
                var column = CloneObject(this.gridData[i+start.row-1][k+start.col-1]);
                column.color = PIXI.utils.hex2string(column.color);
                if (isExits) {
                    data.push(column);
                } else {
                    data[i][k] = column;
                }
            }
        }
        return data;
    }


    /**
     * 得到所有数据
     * @param isExits bool 是否只得到有数据的区块,默认 true
     * @returns {*}
     */
    getAllData(isExits=true) {
        this._clearSelectArea();
        return this.getData(true,isExits);
    }

    /**
     * 回到上一次操作
     */
    undo() {
        this.historyIdx -= 1;

        if (this.historyIdx < 0) {
            this.historyIdx = 19;
        }
        var data = Storage.get('history_'+this.historyIdx);
        if (data) {
            this.gridData = data;
            this._drawData();
        }
    }

    /**
     * 回到前一次操作
     */
    redo() {
        this.historyIdx += 1;
        if (this.historyIdx >=20) {
            this.historyIdx = 0;
        }
        var data = Storage.get('history_'+this.historyIdx);
        if (data) {
            this.gridData = data;
            this._drawData();
        }
    }



    /**
     * 设置缩放比例
     * @param scale 1为100%
     */
    setScale(scale) {
        this.scale = scale;
        this.renderer.view.style.transform = 'scale('+this.scale+','+this.scale+')';
        this.renderer.view.style.transformOrigin = 'left top 0';
    }

    /**
     * 设置标尺文字类型和排序规则
     * @param order string | json 
     * @param type string num | abc
     */
    setStaff(order,type) {
        this.cfg.staff.type = type;
        this.cfg.staff.order = order;
        this._initStaff();
        var i, k,text;
        for (i=0;i<this.gridData.length;i++) {
            for (k=0;k<this.gridData[i].length;k++) {
                if (this.gridData[i][k]) {
                    text = this.staff.ver[i] + ':' + this.staff.hor[k];
                    if (this.gridData[i][k].block == this.gridData[i][k].text) {
                        this.gridData[i][k].text = text;
                    }
                    this.gridData[i][k].block = text;
                }
            }
        }
        this._drawData();
    }

    /**
     * 设置标尺留空
     * @param is_empty
     * @param type
     * @param value
     */
    setStaffEmpty(is_empty=true,type=null,value=null) {
        var staff;
        if (!type || !value) {
            staff = this.staffSelect;
        } else {
            staff = {type:type,value:value};
        }
        if (staff) {
            this.staffEmpty[staff.type][staff.value-1] = is_empty?true:undefined;
            this._initStaff();
        }
    }

    /**
     * 用配置文件设置多标尺位留空
     * @param conf [{type:'hor',value:1}]
     */
    setStaffEmptyConf(conf) {
        if (conf.forEach) {
            conf.forEach((item)=>{
                this.staffEmpty[item.type][item.value] = true;
            });
            this._initStaff();
        }
    }

    /**
     * 得到标尺留空配置
     * @returns {Array}
     */
    getStaffEmptyConf() {
        var conf = [];
        this.staffEmpty.hor.map((item,index)=>{
            conf.push({
                type:'hor',
                value:index
            });
        });

        this.staffEmpty.ver.map((item,index)=>{
            conf.push({
                type:'ver',
                value:index
            });
        });
        return conf;
    }

    /**
     * 设置滚动父节点
     * @param eml
     */
    setScrollParnet(eml) {
        this.parentEml = eml;
        this.eml.point = GetElementXY(this.eml,eml);
    }

    /**
     * 得到当前编排截图
     * @returns {*}
     */
    cutPicture() {
        return this.renderer.view.toDataURL();
    }

    /***
     * 开始工作
     */
    start() {
        this.ticker = new PIXI.ticker.Ticker();
        this.ticker.add((currentTime)=>{
            this._render();
        });
        this.ticker.start();
    }

    destroy() {
        this.eml.removeChild(this.renderer.view);
        this.renderer.destroy();
    }
}